#pragma once

#include <sw/redis++/redis++.h>
#include <memory>
#include <mutex>
#include <chrono>
#include <nlohmann/json.hpp>
#include "../commen/log.hpp"
#include "question.hpp"

namespace oj_redis
{
    using namespace ns_log;
    using json = nlohmann::json;

    class RedisModel
    {
    private:
        static RedisModel *instance_;
        static std::mutex mutex_;
        std::unique_ptr<sw::redis::Redis> redis_;

        // 缓存配置
        struct CacheConfig
        {
            static constexpr int HOT_QUESTIONS_EXPIRE = 3600;   // 1小时
            static constexpr int QUESTION_CACHE_EXPIRE = 86400; // 24小时
            static constexpr int MAX_CACHE_SIZE = 10000;        // 最大缓存大小(MB)
            static constexpr int HOT_NUMBER = 10;               // 热门题目数量
        };

        // 私有构造函数
        RedisModel()
        {
            try
            {
                redis_ = std::make_unique<sw::redis::Redis>("tcp://127.0.0.1:6379");
                InitializeCache();
            }
            catch (const sw::redis::Error &e)
            {
                LogMessage(Error, "Redis initialization failed: %s\n", e.what());
                throw;
            }
        }

        // 初始化缓存
        void InitializeCache()
        {
            try
            {
                // 清理旧缓存
                redis_->flushall();

                // 设置缓存配置
                redis_->set("maxmemory",
                            std::to_string(static_cast<long long>(CacheConfig::MAX_CACHE_SIZE) * 1024 * 1024));
                redis_->set("maxmemory-policy", "allkeys-lru");
            }
            catch (const sw::redis::Error &e)
            {
                LogMessage(Error, "Cache initialization failed: %s\n", e.what());
                throw;
            }
        }

    public:
        static RedisModel *GetInstance()
        {
            if (instance_ == nullptr)
            {
                std::lock_guard<std::mutex> lock(mutex_);
                if (instance_ == nullptr)
                {
                    instance_ = new RedisModel();
                }
            }
            return instance_;
        }

        // 实现缓存问题的方法
        bool CacheQuestion(const Question &question)
        {
            try
            {
                std::string key = "question:" + std::to_string(question.number);
                json j;
                if (question.ToJson(j))
                {
                    redis_->set(key, j.dump());
                    redis_->expire(key, CacheConfig::QUESTION_CACHE_EXPIRE);
                    return true;
                }
                return false;
            }
            catch (const std::exception &e)
            {
                LogMessage(Error, "Cache question failed: %s\n", e.what());
                return false;
            }
        }

        // 实现获取缓存问题的方法
        bool GetCachedQuestion(int number, Question *question)
        {
            try
            {
                std::string key = "question:" + std::to_string(number);
                auto value = redis_->get(key);
                if (value)
                {
                    json j = json::parse(*value);
                    return question->FromJson(j);
                }
                return false;
            }
            catch (const std::exception &e)
            {
                LogMessage(Error, "Get cached question failed: %s\n", e.what());
                return false;
            }
        }

        // 缓存所有题目
        bool CacheAllQuestions(const std::string &questions_json)
        {
            try
            {
                std::string key = "all_questions";
                redis_->set(key, questions_json);
                redis_->expire(key, CacheConfig::QUESTION_CACHE_EXPIRE);
                return true;
            }
            catch (const sw::redis::Error &e)
            {
                LogMessage(Error, "Cache all questions failed: %s\n", e.what());
                return false;
            }
        }

        // 从缓存中获取所有题目
        bool GetAllQuestionsFromCache(std::string *questions_json)
        {
            try
            {
                std::string key = "all_questions";
                if (!redis_->exists(key))
                {
                    return false;
                }
                auto value = redis_->get(key);
                if (value)
                {
                    *questions_json = *value;
                    return true;
                }
                return false;
            }
            catch (const sw::redis::Error &e)
            {
                LogMessage(Error, "Get all questions from cache failed: %s\n", e.what());
                return false;
            }
        }

        // 更新热门题目
        bool UpdateHotQuestions(const std::vector<std::pair<int, int>> &rankings)
        {
            try
            {
                auto pipe = redis_->pipeline();
                std::string key = "hot_questions";

                pipe.del(key);
                for (size_t i = 0; i < std::min(rankings.size(),
                                                static_cast<size_t>(CacheConfig::HOT_NUMBER));
                     ++i)
                {
                    pipe.zadd(key,
                              std::to_string(rankings[i].first),
                              rankings[i].second);
                }
                pipe.expire(key, CacheConfig::HOT_QUESTIONS_EXPIRE);
                pipe.exec();

                return true;
            }
            catch (const sw::redis::Error &e)
            {
                LogMessage(Error, "Update hot questions failed: %s\n", e.what());
                return false;
            }
        }

        // 获取热门题目
        bool GetHotQuestions(std::vector<std::pair<int, int>> *rankings)
        {
            try
            {
                std::string key = "hot_questions";

                if (!redis_->exists(key))
                {
                    return false;
                }

                // 创建一个临时vector来存储结果
                std::vector<std::pair<std::string, double>> results;

                // 使用正确的API调用方式
                // BoundedInterval 构造函数只需要三个参数：min, max, 和一个边界类型
                auto interval = sw::redis::BoundedInterval<double>(
                    std::numeric_limits<double>::lowest(), // 最小值
                    std::numeric_limits<double>::max(),    // 最大值
                    sw::redis::BoundType::CLOSED          // 边界类型（包含两端）
                );

                // 调用 zrevrangebyscore
                redis_->zrevrangebyscore(
                    key,                        // key
                    interval,                   // 分数区间
                    std::back_inserter(results) // 输出迭代器
                );

                // 转换结果
                rankings->clear();
                // 只取前 HOT_NUMBER 个结果
                size_t count = 0;
                for (const auto &[number, score] : results)
                {
                    if (count >= CacheConfig::HOT_NUMBER)
                        break;
                    rankings->emplace_back(std::stoi(number), static_cast<int>(score));
                    ++count;
                }

                return true;
            }
            catch (const std::exception &e)
            {
                LogMessage(Error, "Get hot questions failed: %s\n", e.what());
                return false;
            }
        }

        // 失效题目缓存
        void InvalidateQuestionCache(int number)
        {
            try
            {
                std::string key = "question:" + std::to_string(number);
                redis_->del(key);
            }
            catch (const sw::redis::Error &e)
            {
                LogMessage(Warning, "Invalidate question cache failed: %s\n", e.what());
            }
        }

        // 失效所有题目缓存
        void InvalidateAllQuestionsCache()
        {
            try
            {
                redis_->del("all_questions");
            }
            catch (const sw::redis::Error &e)
            {
                LogMessage(Warning, "Invalidate all questions cache failed: %s\n", e.what());
            }
        }

        // 防止拷贝
        RedisModel(const RedisModel &) = delete;
        RedisModel &operator=(const RedisModel &) = delete;
    };

    // 静态成员初始化
    RedisModel *RedisModel::instance_ = nullptr;
    std::mutex RedisModel::mutex_;
}